# -*- coding: utf-8 -*-
# @Author: Cursor
# @Date: 2025-01-09
# @Last Modified by: Tim Liu
# @Last Modified time: 2025-01-09

# @Description: Custom function registry

import importlib
import requests

class CustomFunctionRegistry:
    """
    A registry for managing custom functions. Supports inline functions and Azure Functions.

    Attributes:
        registry (dict): A dictionary to store registered custom functions.
    """

    def __init__(self):
        """
        Initialize the CustomFunctionRegistry with an empty registry.
        """
        self.registry = {}

    def register(self, action_id: str, action_name: str, function_type: str, function_reference: str, action_description: str, condition: str = None):
        """
        Register a custom function in the registry.

        Args:
            action_id (str): The unique identifier for the action.
            action_name (str): The name of the action.
            function_type (str): The type of the function ('inline', 'azure', or 'aws').
            function_reference (str): The reference to the function (module and function name for inline, URL for Azure).
            action_description (str): A description of the action.
            condition (str, optional): A condition to evaluate before calling the function. Defaults to None.
        """
        self.registry[action_id] = {
            "name": action_name,
            "type": function_type,
            "reference": function_reference,
            "description": action_description,
            "condition": condition
        }

    def get_custom_function(self, action_id: str):
        """
        Retrieve a custom function from the registry.

        Args:
            action_id (str): The unique identifier for the action.

        Returns:
            dict: The custom function information, or None if not found.
        """
        return self.registry.get(action_id)

    def evaluate_condition(self, condition: str, **kwargs) -> bool:
        """
        Evaluate a condition string with the provided keyword arguments.

        Args:
            condition (str): The condition string to evaluate.
            **kwargs: Keyword arguments to use in the evaluation.

        Returns:
            bool: The result of the condition evaluation.
        """
        try:
            return eval(condition, {}, kwargs)
        except Exception as e:
            return False

    def call_custom_function(self, action_id: str, **kwargs):
        """
        Call a custom function based on its action ID.

        Args:
            action_id (str): The unique identifier for the action.
            **kwargs: Keyword arguments to pass to the custom function.

        Returns:
            Any: The result of the custom function call, or None if the function is not found or the condition is not met.

        Raises:
            Exception: If the function type is unknown or if there is an error calling an Azure Function.
        """
        custom_function_info = self.get_custom_function(action_id)
        if not custom_function_info:
            return None

        condition = custom_function_info.get('condition')
        if condition and not self.evaluate_condition(condition, **kwargs):
            return None

        function_type = custom_function_info['type']
        function_reference = custom_function_info['reference']

        if function_type == 'inline':
            module_name, function_name = function_reference.rsplit('.', 1)
            module = importlib.import_module(module_name)
            custom_function = getattr(module, function_name)
            return custom_function(**kwargs)
        elif function_type == 'azure':
            response = requests.post(function_reference, json={'kwargs': kwargs})
            if response.status_code == 200:
                return response.json()
            else:
                raise Exception(f"Error calling Azure Function: {response.text}")
        else:
            raise Exception(f"Unknown function type: {function_type}")

# Create a global registry instance
custom_function_registry = CustomFunctionRegistry()